import { ForwardedRef, forwardRef, useImperativeHandle, useRef, useState } from 'react';
import { CodeContainerType } from '../../core/types';
import CodeEdit from '../CodeEdit';
import FolderSide from '../FolderSide';
import Terminal, { IReactTerminalRef } from '../Terminal';
import './index.scss'
import { Button, message, UploadFile } from 'antd';
import { languageMap } from '../../common/constants';
import { apiCreateProjectToServer, apiDownProject, apiGetProjectDownloadUrl, apiUpdateProjectToServer } from '../../api';
import { SaveOutlined } from '@ant-design/icons';
import { generateUniqueString } from '../../common/Utils';

interface IProps {
    type: CodeContainerType
}

export interface IDirData {
    projectName: string;
    content: {
        path: string;
        codeType: string
        code: string;
    }[];
}

export interface TreeDataNode {
    title: string;
    code?: string;
    codeType?: string;
    key: string;
    isLeaf: boolean;
    children: TreeDataNode[];
}

export interface ICodeContainerRef {
    dirData: IDirData | undefined;
    setDirData: React.Dispatch<React.SetStateAction<IDirData | undefined>>
    setLoading: React.Dispatch<React.SetStateAction<boolean>>
    createProjectToServer: (data: IDirData) => void
}

const CodeContainer = forwardRef((props: IProps, ref: ForwardedRef<ICodeContainerRef>) => {
    const { type } = props;
    const [currentCodePath, setCurrentCodePath] = useState<string>('');
    const [dirData, setDirData] = useState<IDirData>();
    const [translateLoading, setTranslateLoading] = useState<boolean>(false);
    const terminalRef = useRef<IReactTerminalRef>(null); // DOM 容器引用

    useImperativeHandle(ref, () => {
        return {
            dirData,
            setDirData,
            setLoading: setTranslateLoading,
            createProjectToServer,
        };
    }, [dirData]);



    async function transformFilesToOutput(
        files: UploadFile[]
    ): Promise<IDirData> {
        const projectName = files[0].originFileObj!.webkitRelativePath.split('/')[0] + '-' + generateUniqueString();
        const contentPromises = files.map(async (file) => {
            const code = await getCode(file.originFileObj!) // 读取文件内容为字符串
            return {
                path: file.originFileObj!.webkitRelativePath.replace(/^[^/]*\//, ""), // 使用文件名作为路径
                ...code
            };
        });
        const content = await Promise.all(contentPromises); // 等待所有异步任务完成
        return {
            projectName,
            content,
        };
    }

    const createProjectToServer = (data: IDirData) => {
        apiCreateProjectToServer(data).then((res) => {
            if (terminalRef.current) {
                terminalRef.current.writeTerminal('cd ' + normalizePath(res.projectPath))
                terminalRef.current.writeTerminal('\n')
                terminalRef.current.writeTerminal(`clear`)
            }

        })
    }

    const onSiderFolderChange = (files: UploadFile[]) => {
        transformFilesToOutput(files).then((data) => {
            setDirData(data)
            createProjectToServer(data)
        })
    }

    const getCode = async (file: File) => {
        const blob = new Blob([file], { type: file.type });
        const text = await blob.text()
        const fileExtension = file.name.split('.').pop()?.toLowerCase();
        const detectedLanguage = fileExtension ? languageMap[fileExtension] : 'plaintext';
        return {
            code: text || '',
            codeType: detectedLanguage
        }
    }

    function convertToNestedStructure(input: IDirData): TreeDataNode[] {
        const root: TreeDataNode = {
            title: input.projectName,
            code: "",
            key: input.projectName,
            children: [],
            isLeaf: false
        };
        // Helper function to insert a file into the tree
        function insertIntoTree(node: TreeDataNode, pathParts: string[], code: string) {
            if (pathParts.length === 0) return;

            const [currentPart, ...restParts] = pathParts;
            let child = node.children?.find((child) => child.title === currentPart);

            if (!child) {
                child = {
                    title: currentPart,
                    code: "",
                    key: `${node.key}/${currentPart}`,
                    children: [],
                    isLeaf: false
                };
                node.children?.push(child);
            }
            if (restParts.length === 0) {
                child.code = code;
                child.isLeaf = true;
            } else {
                insertIntoTree(child, restParts, code);
            }
        }
        // Populate the tree
        input.content.forEach(({ path, code }) => {
            const pathParts = path.split("/");
            insertIntoTree(root, pathParts, code);
        });
        return [root];
    }
    const currentfile = dirData?.content.find((item) => item.path === currentCodePath);

    const handleCodeEdit = (code: string) => {
        if (dirData && currentfile) {
            currentfile.code = code;
            setDirData({ ...dirData })
        }
    }
    const handleExport = () => {
        if (!dirData) {
            message.warning('Data empty')
            return;
        }
        if (translateLoading) {
            message.warning('translating, please wait a moment')
            return
        }
        apiGetProjectDownloadUrl(dirData).then((res) => {
            if (res.downloadUrl) {
                message.success('Export successfully')
                apiDownProject(res.downloadUrl)
            } else {
                message.error('Export failed')
            }
        })
    }

    const handleSave = () => {
        if (!dirData) {
            message.warning('Data empty')
            return;
        }
        apiUpdateProjectToServer(dirData!).then((res) => {
            if (res.projectPath) {
                message.success('Save successfully')
            } else {
                message.error('Save failed')
            }
        })
    }

    function normalizePath(input: string) {
        return input.replace(/\\/g, '/'); // 将所有反斜杠替换为正斜杠
    }

    return <div className="code-main-container">
        <div className='content' >
            <FolderSide
                loading={translateLoading}
                type={type}
                onExport={handleExport}
                treeData={dirData ? convertToNestedStructure(dirData) : undefined}
                onFolderChange={onSiderFolderChange}
                onFilePathSelect={setCurrentCodePath}
            />
            <CodeEdit language={currentfile?.codeType || ''} code={currentfile?.code || ''} onCodeChange={handleCodeEdit} />
            <Terminal ref={terminalRef} />
            <Button className='save-btn' onClick={handleSave} type='primary' icon={<SaveOutlined />}>save</Button>
        </div>
    </div>
})
export default CodeContainer;